package org.apache.osgimaker.editors.content;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.apache.osgimaker.editors.model.Bundle;
import org.apache.osgimaker.editors.model.BundleListEditModel;
import org.apache.osgimaker.utils.BundleDetailsTableLabelProvider;
import org.eclipse.core.resources.IProject;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.forms.IFormPart;
import org.eclipse.ui.forms.IManagedForm;
import org.eclipse.ui.forms.IPartSelectionListener;
import org.eclipse.ui.forms.SectionPart;
import org.eclipse.ui.forms.editor.IFormPage;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;

public class BundleDetailsPart extends SectionPart implements PropertyChangeListener,IPartSelectionListener{

	private BundleListEditModel model;
	private IManagedForm managedForm;
	
	private List<String> classes = new ArrayList<String>();
	
	private Table table;
	private TableViewer viewer;
	private String modifyBundleId;
	
	public BundleDetailsPart(Composite parent, FormToolkit toolkit, int style) {
		super(parent, toolkit, style);
		createSection(getSection(), toolkit);
	}
	
	private void createSection(Section section, FormToolkit toolkit) {
		section.setText("Bundle Classes Details");
		section.setDescription("This selected bundle should include the following classes");

		ToolBar toolbar = new ToolBar(section, SWT.FLAT);
		section.setTextClient(toolbar);
		final ToolItem addItem = new ToolItem(toolbar, SWT.PUSH);
		addItem.setImage(PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_ADD));
		addItem.setToolTipText("Add");

		final ToolItem removeItem = new ToolItem(toolbar, SWT.PUSH);
		removeItem.setImage(PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_TOOL_DELETE));
		removeItem.setDisabledImage(PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_TOOL_DELETE_DISABLED));
		removeItem.setToolTipText("Remove");
		removeItem.setEnabled(false);

		Composite composite = toolkit.createComposite(section);
		section.setClient(composite);

		table = toolkit.createTable(composite, SWT.FULL_SELECTION | SWT.MULTI | SWT.BORDER);

		viewer = new TableViewer(table);
		viewer.setContentProvider(new ArrayContentProvider());
		viewer.setLabelProvider(new BundleDetailsTableLabelProvider());

		viewer.addSelectionChangedListener(new ISelectionChangedListener() {
			public void selectionChanged(SelectionChangedEvent event) {
				removeItem.setEnabled(!viewer.getSelection().isEmpty());
			}
		});
		
		addItem.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				doAddClasses();
			}
		});
		removeItem.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				doRemoveClasses();
			}
		});

		// Layout
		GridLayout layout = new GridLayout(1, false);
		layout.marginHeight = 0;
		layout.marginWidth = 0;
		composite.setLayout(layout);

		GridData gd;

		gd = new GridData(SWT.FILL, SWT.FILL, true, true);
		gd.heightHint = 75;
		gd.widthHint = 75;
		table.setLayoutData(gd);
	}
	
	private void doAddClasses() {
		InputDialog input = new InputDialog(getSection().getShell(),
				"Add new class for this OSGi bundle", "Please input class name here:",
				"", null);
		if (input.open() == Window.OK) {
			String newBundleName = input.getValue();
			if(newBundleName != null && !newBundleName.trim().equals("")&& !classes.contains(newBundleName)){
				List<String> added = new LinkedList<String>();
				if(classes.add(newBundleName)) {
					added.add(newBundleName);
				}
				
				// Update the model and view
				if(!added.isEmpty()) {
					viewer.add(added.toArray(new String[added.size()]));
					markDirty();
				}
			}	
		}
	}
	
	private void doRemoveClasses(){
		IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
		if(!selection.isEmpty()) {
			Iterator<?> elements = selection.iterator();
			List<Object> removed = new LinkedList<Object>();
			while(elements.hasNext()) {
				Object pkg = elements.next();
				if(classes.remove(pkg))
					removed.add(pkg);
			}

			if(!removed.isEmpty()) {
				viewer.remove(removed.toArray(new String[removed.size()]));
				markDirty();
			}
		}
	}

	@Override
	public void commit(boolean onSave) {
		super.commit(onSave);
		Bundle bundle = model.getBundleById(this.modifyBundleId);
		bundle.setClasses(classes);
		model.updateBundleClasses(this.modifyBundleId, bundle);
		
		managedForm.dirtyStateChanged();
	}

	@Override
	public void refresh() {
		if (this.modifyBundleId!=null){
			Bundle bundle = model.getBundleById(this.modifyBundleId);
			if( bundle!=null ){
				classes = bundle.getClasses();
				viewer.setInput(classes);
			}
		}
		
		super.refresh();
	}
	
	@Override
	public void initialize(IManagedForm form) {
		super.initialize(form);
		this.managedForm = form;
		model = (BundleListEditModel) form.getInput();
	}
	
	@Override
	public void dispose() {
		super.dispose();
		if(this.model != null)
			this.model.removePropertyChangeListener(this);
	}
	
	@Override
	public void selectionChanged(IFormPart part, ISelection selection) {
		Object[] tmp = ((IStructuredSelection) selection).toArray();
		for(int i=0;i<tmp.length;i++){
			String id = tmp[i].toString();
			Bundle bundle = model.getBundleById(id);
			classes = bundle.getClasses();
			viewer.setInput(classes);
			modifyBundleId = id;
			break;
		}
	}

	@Override
	public void propertyChange(PropertyChangeEvent arg0) {
		IFormPage page = (IFormPage) getManagedForm().getContainer();
		if(page.isActive()) {
			refresh();
		} else {
			markStale();
		}
	}
	
	private IJavaProject getJavaProject() {
		IFormPage page = (IFormPage) getManagedForm().getContainer();
		IEditorInput input = page.getEditorInput();
		if(!IFileEditorInput.class.isInstance(input)) {
			return null;
		}
		IProject project = ((IFileEditorInput) input).getFile().getProject();
		return JavaCore.create(project);
	}
	
	public interface IPackageFilter {
		boolean select(String packageName);
	}
}
